
#define DIRECTINPUT_VERSION 0x0800

#include <cegfx/cekeyboard.h>
#include <stdio.h>

#define MAX_KEYS 256

#define CHECK_KEY(i) if ((i) >= MAX_KEYS || (i) < 0) return false
#define KEY_DOWN(idx, key) ((keys[(idx)][(key)] & (BYTE)0x80) != 0)
#define KEY_UP(idx, key) ((keys[(idx)][(key)] & (BYTE)0x80) == 0)

ceKeyboard::ceKeyboard()
	:	keyboardDevice(0)
	, idx0(0)
	, idx1(1)
{
}

ceKeyboard::~ceKeyboard ()
{
	if (keyboardDevice)
	{
		keyboardDevice->Release ();
	}
}

IQF_IMPLEMENTATION_BEGIN(ceKeyboard);
IQF_IMPLEMENTATION_END ();

bool ceKeyboard::Initialize (LPDIRECTINPUT8 input)
{
	ZeroMemory(keys, sizeof (keys));
	if (FAILED(input->CreateDevice(GUID_SysKeyboard, (LPDIRECTINPUTDEVICE8*)(&keyboardDevice), 0))) return false;
	if (FAILED(keyboardDevice->SetDataFormat(&c_dfDIKeyboard))) return false;
	if (keyboardDevice)
	{
		keyboardDevice->AddRef ();
	}

	return true;
}

bool ceKeyboard::UpdateState ()
{
	HRESULT hr = keyboardDevice->Poll ();
	if (FAILED(hr))
	{
		hr = keyboardDevice->Acquire();
		while (hr == DIERR_INPUTLOST)
		{
			hr = keyboardDevice->Acquire ();
		}
		if (FAILED(keyboardDevice->Poll ())) return false;
	}
	if (idx0)
	{
		idx0 = 0;
		idx1 = 1;
	}
	else
	{
		idx0 = 1;
		idx1 = 0;
	}

	keyboardDevice->GetDeviceState (256, keys[idx0]);
	return true;
}


bool ceKeyboard::IsKeyDown (int key) const
{
	CHECK_KEY(key);
	return KEY_DOWN(idx0, key);
}

bool ceKeyboard::IsKeyUp (int key) const
{
	CHECK_KEY(key);
	return KEY_UP(idx0, key);
}

bool ceKeyboard::IsKeyPressed (int key) const
{
	CHECK_KEY(key);
	return KEY_DOWN(idx0, key) && KEY_UP(idx1, key);
}

bool ceKeyboard::IsKeyReleased (int key) const
{
	CHECK_KEY(key);
	return KEY_UP(idx0, key) && KEY_DOWN(idx1, key);
}
